/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_orm.htm
 *
 * Zhiqim ORM is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.orm.dbo;

import java.sql.Timestamp;
import java.util.Map.Entry;

import org.zhiqim.kernel.model.maps.LinkedMapSS;
import org.zhiqim.kernel.util.Asserts;
import org.zhiqim.kernel.util.Classes;
import org.zhiqim.orm.ORMConstants;

/**
 * 对象比较器，用于排序，其中静态方法用于条件比较
 *
 * @version v1.0.0 @author zouzhigang 2017-8-23 新建与整理
 */
public class Comparator<T> implements java.util.Comparator<T>, ORMConstants
{
    private Selector selector;
    
    public Comparator(Selector selector)
    {
        this.selector = selector;
    }
    
    @Override
    public int compare(T o1, T o2)
    {
        if (selector == null)
            return 0;
        
        LinkedMapSS orderbyMap = selector.getOrderby();
        if (orderbyMap == null || orderbyMap.isEmpty())
            return 0;
        
        for (Entry<String, String> entry : orderbyMap.entrySet())
        {
            String field = entry.getKey();
            String orderby = entry.getValue();
            boolean isAsc = ASC.equals(orderby);
            
            Object value1 = Classes.getFieldValue(o1, field);
            Object value2 = Classes.getFieldValue(o2, field);
            int val = compareValue(value1, value2);
            if (val == 0)
                continue;
            
            return ((val < 0 && isAsc) || (val > 0 && !isAsc))?-1:1;
        }
        
        return 0;
    }
    
    /**
     * 比较两个对象值，9种数据库类型转为Java的6种类型
     * 
     * @param value1    值1
     * @param value2    值2
     * @return          =0表示相等，>0表示前者大，<0表示后者大
     */
    public static int compareValue(Object value1, Object value2)
    {
        Asserts.as(value1.getClass() == value2.getClass()?null:"比较的两个对象类型不一致");
        
        switch (value1.getClass().getName().hashCode())
        {
        case BOOLEAN_OBJ_CODE:
        {
            boolean v1 = (Boolean)value1;
            boolean v2 = (Boolean)value2;
            int v11 = v1?1:0;
            int v22 = v2?1:0;
            return v11 - v22;
        }
        case INT_OBJ_CODE:
        {
            int v1 = (Integer)value1;
            int v2 = (Integer)value2;
            return v1 - v2;
        }
        case LONG_OBJ_CODE:
        {
            long v1 = (Long)value1;
            long v2 = (Long)value2;
            return v1 == v2?0:(v1 > v2)?1:-1;
        }
        case STRING_CODE:
        {
            String v1 = (String)value1;
            String v2 = (String)value2;
            return v1.compareTo(v2);
        } 
        case DOUBLE_OBJ_CODE:
        {
            double v1 = (Double)value1;
            double v2 = (Double)value2;
            return v1 == v2?0:(v1 > v2)?1:-1;
        }
        case TIMESTAMP_CODE:
        {
            Timestamp v1 = (Timestamp)value1;
            Timestamp v2 = (Timestamp)value2;
            long v11 = v1.getTime();
            long v22 = v2.getTime();
            return v11 == v22?0:(v11 > v22)?1:-1;
        } 
        default:
            throw Asserts.exception("比较的对象类型不是ORM支持的类型");
        }
    }
}
